package com.ouc.pampas;
import com.fasterxml.jackson.databind.JavaType;
import com.github.kevinsawicki.http.HttpRequest;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import io.terminus.common.exception.ServiceException;
import io.terminus.common.utils.JsonMapper;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;

@Component
public class HttpExecutor
  extends Executor<Map<String, Object>>
{
  private static final Logger log = LoggerFactory.getLogger(HttpExecutor.class);
  private static final Splitter splitter = Splitter.on(':').trimResults().omitEmptyStrings();
  private static final JsonMapper jsonMapper = JsonMapper.JSON_NON_EMPTY_MAPPER;
  private static final JavaType collectionType = jsonMapper.createCollectionType(HashMap.class, new Class[] { String.class, Object.class });
  
  public Map<String, Object> exec(Service service, Map<String, Object> params)
  {
    HttpTarget httpTarget = HttpTarget.parseFrom(service);
    HttpRequest httpRequest;
    switch (httpTarget.method.ordinal())
    {
    case 1: 
      httpRequest = HttpRequest.get(httpTarget.uri, params, true);
      break;
    case 2: 
      httpRequest = HttpRequest.post(httpTarget.uri, params, true);
      break;
    case 3: 
      httpRequest = HttpRequest.put(httpTarget.uri, params, true);
      break;
    case 4: 
      httpRequest = HttpRequest.delete(httpTarget.uri, params, true);
      break;
    default: 
      throw new IllegalStateException("Unsupported http method");
    }
    if (!httpRequest.ok())
    {
      log.error("http service error: code {}, params {}, body {}", new Object[] { Integer.valueOf(httpRequest.code()), params, httpRequest.body() });
      throw new ServiceException("http service error");
    }
    String response = httpRequest.body();
    return (Map)jsonMapper.fromJson(response, collectionType);
  }
  
  private static class HttpTarget
  {
    private static Map<Object,Object> methodMapping = ImmutableMap.builder().put("GET", HttpMethod.GET).put("POST", HttpMethod.POST).put("DELETE", HttpMethod.DELETE).put("PUT", HttpMethod.PUT).build();
    private HttpMethod method;
    private String uri;
    
    protected static HttpTarget parseFrom(Service service)
    {
      HttpTarget target = new HttpTarget();
      List<String> splitResult = HttpExecutor.splitter.splitToList(service.getUri());
      target.method = ((HttpMethod)methodMapping.get(((String)splitResult.get(0)).toUpperCase()));
      target.uri = ((String)splitResult.get(1));
      return target;
    }
  }
}
